﻿using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TrackGroupControl
{
    protected const int DEFAULT_ROW_HEIGHT = 0x11;
    private DirectorControl directorControl;
    public bool isExpanded = true;
    protected Texture LabelPrefix;
    private Rect position;
    private float sortingOptionsWidth = 32f;
    protected DirectorControlState state;
    public static TrackGroupStyles styles;
    private Dictionary<TimelineTrackWrapper, TimelineTrackControl> timelineTrackMap = new Dictionary<TimelineTrackWrapper, TimelineTrackControl>();
    protected const int TRACK_GROUP_ICON_WIDTH = 0x10;
    protected TrackGroupWrapper trackGroup;

    protected virtual void addTrackContext()
    {
    }

    protected void delete()
    {
        Undo.DestroyObjectImmediate(this.trackGroup.Behaviour.gameObject);
    }

    internal float GetHeight()
    {
        float num = 17f;
        if (this.isExpanded)
        {
            foreach (TimelineTrackControl control in this.timelineTrackMap.Values)
            {
                num += control.Rect.height;
            }
        }
        return num;
    }

    public virtual void Initialize()
    {
        this.LabelPrefix = styles.DirectorGroupIcon.normal.background;
    }

    internal static void InitStyles(GUISkin skin)
    {
        if (styles == null)
        {
            styles = new TrackGroupStyles(skin);
        }
    }

    protected virtual void showHeaderContextMenu()
    {
        GenericMenu menu = new GenericMenu();
        menu.AddItem(new GUIContent("Delete"), false, new GenericMenu.MenuFunction(this.delete));
        menu.ShowAsContext();
    }

    public virtual void Update(TrackGroupWrapper trackGroup, DirectorControlState state, Rect position, Rect header, Rect content)
    {
        this.position = position;
        this.trackGroup = trackGroup;
        this.state = state;
        if (trackGroup.Behaviour != null)
        {
            if (trackGroup.HasChanged)
            {
                this.updateTrackMap(trackGroup);
            }
            this.updateHeaderBackground(header);
            this.updateContentBackground(content);
            this.updateHeaderContent(header);
            if (this.isExpanded)
            {
                Rect rect = new Rect(header.x, header.y, content.x, header.height);
                this.UpdateTracks(state, rect, content);
            }
        }
    }

    protected virtual void updateContentBackground(Rect content)
    {
        GUI.Box(this.position, string.Empty, styles.trackGroupArea);
    }

    protected virtual void updateHeaderBackground(Rect position)
    {
    }

    protected virtual void updateHeaderContent(Rect header)
    {
        Rect position = new Rect(header.x, header.y, header.width / 2f, 17f);
        string name = this.trackGroup.Behaviour.name;
        string text = (name.Length < 0x12) ? name : (name.Substring(0, 0x11) + "...");
        GUIContent content = new GUIContent(text, this.LabelPrefix);
        bool flag = EditorGUI.Foldout(position, this.isExpanded, content, true);
        if (flag != this.isExpanded)
        {
            this.isExpanded = flag;
            EditorPrefs.SetBool(string.Format("{0}.{1}", this.trackGroup.Behaviour.GetInstanceID(), "isExpanded"), this.isExpanded);
        }
        int controlID = GUIUtility.GetControlID(this.trackGroup.Behaviour.GetInstanceID(), FocusType.Passive, position);
        if (((Event.current.GetTypeForControl(controlID) == EventType.MouseDown) && position.Contains(Event.current.mousePosition)) && (Event.current.button == 1))
        {
            this.showHeaderContextMenu();
        }
        this.updateHeaderControl1(new Rect(header.width - 96f, header.y, 16f, 16f));
        this.updateHeaderControl2(new Rect(header.width - 80f, header.y, 16f, 16f));
        this.updateHeaderControl3(new Rect(header.width - 64f, header.y, 16f, 16f));
        this.updateHeaderControl4(new Rect(header.width - 48f, header.y, 16f, 16f));
        this.updateHeaderControl5(new Rect(header.width - 32f, header.y, 16f, 16f));
        this.updateHeaderControl6(new Rect(header.width - 16f, header.y, 16f, 16f));
    }

    protected virtual void updateHeaderControl1(Rect position)
    {
    }

    protected virtual void updateHeaderControl2(Rect position)
    {
    }

    protected virtual void updateHeaderControl3(Rect position)
    {
    }

    protected virtual void updateHeaderControl4(Rect position)
    {
    }

    protected virtual void updateHeaderControl5(Rect position)
    {
        Color color = GUI.color;
        int num = 0;
        using (IEnumerator<TimelineTrackWrapper> enumerator = this.trackGroup.Tracks.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                TimelineTrackWrapper current = enumerator.Current;
                num++;
            }
        }
        GUI.color = (num > 0) ? Color.green : Color.red;
        if (GUI.Button(position, string.Empty, styles.addIcon))
        {
            this.addTrackContext();
        }
        GUI.color = color;
    }

    protected virtual void updateHeaderControl6(Rect position)
    {
        if (GUI.Button(position, string.Empty, styles.InspectorIcon))
        {
            EditorGUIUtility.PingObject(this.trackGroup.Behaviour.gameObject.GetInstanceID());
            Selection.activeGameObject = this.trackGroup.Behaviour.gameObject;
        }
    }

    private void updateTrackMap(TrackGroupWrapper trackGroup)
    {
        bool flag = false;
        foreach (TimelineTrackWrapper wrapper in trackGroup.Tracks)
        {
            TimelineTrackControl control = null;
            if (!this.timelineTrackMap.TryGetValue(wrapper, out control))
            {
                flag = true;
                System.Type[] allSubTypes = DirectorControlHelper.GetAllSubTypes(typeof(TimelineTrackControl));
                System.Type type = typeof(TimelineTrackControl);
                int num = 0x7fffffff;
                foreach (System.Type type2 in allSubTypes)
                {
                    System.Type c = null;
                    foreach (CutsceneTrackAttribute attribute in type2.GetCustomAttributes(typeof(CutsceneTrackAttribute), true))
                    {
                        if (attribute != null)
                        {
                            c = attribute.TrackType;
                        }
                    }
                    if (c == wrapper.Behaviour.GetType())
                    {
                        type = type2;
                        num = 0;
                        break;
                    }
                    if ((c != null) && wrapper.Behaviour.GetType().IsSubclassOf(c))
                    {
                        System.Type baseType = wrapper.Behaviour.GetType();
                        int num2 = 0;
                        while ((baseType != null) && (baseType != c))
                        {
                            baseType = baseType.BaseType;
                            num2++;
                        }
                        if (num2 <= num)
                        {
                            num = num2;
                            type = type2;
                        }
                    }
                }
                control = (TimelineTrackControl) Activator.CreateInstance(type);
                control.TrackGroupControl = this;
                control.TargetTrack = wrapper;
                this.timelineTrackMap.Add(wrapper, control);
            }
        }
        List<TimelineTrackWrapper> list = new List<TimelineTrackWrapper>();
        foreach (TimelineTrackWrapper wrapper2 in this.timelineTrackMap.Keys)
        {
            bool flag2 = false;
            foreach (TimelineTrackWrapper wrapper3 in trackGroup.Tracks)
            {
                if (wrapper2.Equals(wrapper3))
                {
                    flag2 = true;
                    break;
                }
            }
            if (!flag2)
            {
                list.Add(wrapper2);
            }
        }
        foreach (TimelineTrackWrapper wrapper4 in list)
        {
            flag = true;
            this.timelineTrackMap.Remove(wrapper4);
        }
        if (flag)
        {
            SortedDictionary<int, TimelineTrackWrapper> dictionary = new SortedDictionary<int, TimelineTrackWrapper>();
            List<TimelineTrackWrapper> list2 = new List<TimelineTrackWrapper>();
            foreach (TimelineTrackWrapper wrapper5 in this.timelineTrackMap.Keys)
            {
                if ((wrapper5.Ordinal >= 0) && !dictionary.ContainsKey(trackGroup.Ordinal))
                {
                    dictionary.Add(wrapper5.Ordinal, wrapper5);
                }
                else
                {
                    list2.Add(wrapper5);
                }
            }
            int num3 = 0;
            foreach (TimelineTrackWrapper wrapper6 in dictionary.Values)
            {
                wrapper6.Ordinal = num3;
                num3++;
            }
            foreach (TimelineTrackWrapper wrapper7 in list2)
            {
                wrapper7.Ordinal = num3;
                num3++;
            }
        }
        trackGroup.HasChanged = false;
    }

    protected virtual void UpdateTracks(DirectorControlState state, Rect header, Rect content)
    {
        SortedDictionary<int, TimelineTrackWrapper> dictionary = new SortedDictionary<int, TimelineTrackWrapper>();
        foreach (TimelineTrackWrapper wrapper in this.timelineTrackMap.Keys)
        {
            TimelineTrackControl control = this.timelineTrackMap[wrapper];
            control.TargetTrack = wrapper;
            dictionary.Add(wrapper.Ordinal, wrapper);
        }
        float top = header.y + 17f;
        foreach (int num2 in dictionary.Keys)
        {
            TimelineTrackWrapper wrapper2 = dictionary[num2];
            TimelineTrackControl control2 = this.timelineTrackMap[wrapper2];
            float height = control2.Rect.height;
            Rect position = new Rect(content.x, top, content.width, height);
            Rect rect2 = new Rect(header.x, top, header.width, height);
            Rect rect3 = new Rect(header.x, top, header.width - this.sortingOptionsWidth, height);
            Rect rect4 = new Rect(rect3.x + rect3.width, top, this.sortingOptionsWidth / 2f, 16f);
            Rect rect5 = new Rect(rect4.x + (this.sortingOptionsWidth / 2f), top, this.sortingOptionsWidth / 2f, 16f);
            control2.UpdateTrackBodyBackground(position);
            control2.UpdateHeaderBackground(rect2);
            GUILayout.BeginArea(position);
            Rect rect6 = position;
            control2.UpdateTrackContents(state, rect6);
            GUILayout.EndArea();
            control2.UpdateHeaderContents(state, rect3, rect2);
            GUI.enabled = num2 > 0;
            if (GUI.Button(rect4, string.Empty, DirectorControl.DirectorControlStyles.UpArrowIcon))
            {
                wrapper2.Ordinal--;
                TimelineTrackWrapper targetTrack = this.timelineTrackMap[dictionary[num2 - 1]].TargetTrack;
                targetTrack.Ordinal++;
            }
            GUI.enabled = num2 < (dictionary.Count - 1);
            if (GUI.Button(rect5, string.Empty, DirectorControl.DirectorControlStyles.DownArrowIcon))
            {
                wrapper2.Ordinal++;
                TimelineTrackWrapper wrapper3 = this.timelineTrackMap[dictionary[num2 + 1]].TargetTrack;
                wrapper3.Ordinal--;
            }
            GUI.enabled = true;
            top += height;
        }
    }

    public DirectorControl DirectorControl
    {
        get
        {
            return this.directorControl;
        }
        set
        {
            this.directorControl = value;
        }
    }

    public TrackGroupWrapper TrackGroup
    {
        get
        {
            return this.trackGroup;
        }
        set
        {
            this.trackGroup = value;
        }
    }

    public class TrackGroupStyles
    {
        public GUIStyle ActorGroupIcon;
        public GUIStyle addIcon;
        public GUIStyle CharacterGroupIcon;
        public GUIStyle DirectorGroupIcon;
        public GUIStyle InspectorIcon;
        public GUIStyle MultiActorGroupIcon;
        public GUIStyle pickerStyle;
        public GUIStyle trackGroupArea;

        public TrackGroupStyles(GUISkin skin)
        {
            this.addIcon = skin.FindStyle("Add");
            this.InspectorIcon = skin.FindStyle("InspectorIcon");
            this.trackGroupArea = skin.FindStyle("Track Group Area");
            this.DirectorGroupIcon = skin.FindStyle("DirectorGroupIcon");
            this.ActorGroupIcon = skin.FindStyle("ActorGroupIcon");
            this.MultiActorGroupIcon = skin.FindStyle("MultiActorGroupIcon");
            this.CharacterGroupIcon = skin.FindStyle("CharacterGroupIcon");
            this.pickerStyle = skin.FindStyle("Picker");
        }
    }
}

